package com.studyroom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.studyroom.entity.Reservation;
import com.studyroom.entity.Seat;
import com.studyroom.entity.StudyRoom;
import com.studyroom.mapper.ReservationMapper;
import com.studyroom.mapper.SeatMapper;
import com.studyroom.mapper.StudyRoomMapper;
import com.studyroom.service.SeatService;
import com.studyroom.service.StudyRoomService;
import com.studyroom.vo.SeatAvailabilityVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.studyroom.exception.ServiceException;
import java.io.Serializable;

@Slf4j
@Service
public class StudyRoomServiceImpl extends ServiceImpl<StudyRoomMapper, StudyRoom> implements StudyRoomService {
    
    private final SeatMapper seatMapper;
    private final ReservationMapper reservationMapper;
    @Autowired
    private SeatService seatService;
    
    public StudyRoomServiceImpl(SeatMapper seatMapper, ReservationMapper reservationMapper) {
        this.seatMapper = seatMapper;
        this.reservationMapper = reservationMapper;
    }

    @Override
    public List<SeatAvailabilityVO> getSeatAvailability(
        Long roomId, 
        LocalDateTime startTime, 
        LocalDateTime endTime
    ) {
        log.info("查询座位可用性 - roomId: {}, startTime: {}, endTime: {}", roomId, startTime, endTime);
        
        // 1. 获取自习室的所有启用的座位，不再考虑is_occupied字段
        List<Seat> seats = seatMapper.selectList(
            new LambdaQueryWrapper<Seat>()
                .eq(Seat::getRoomId, roomId)
                .eq(Seat::getStatus, 1)  // 只获取状态为启用的座位
                .orderByAsc(Seat::getSeatNumber)
        );
        
        // 2. 查询有效时间段内的所有活跃预约（状态为1-待使用或2-使用中）
        List<Reservation> reservations = reservationMapper.selectList(
            new LambdaQueryWrapper<Reservation>()
                .eq(Reservation::getRoomId, roomId)
                .in(Reservation::getStatus, 1, 2)  // 只考虑待使用和使用中的预约
                .and(w -> w
                    .between(Reservation::getStartTime, startTime, endTime)  // 预约开始时间在查询时间段内
                    .or()
                    .between(Reservation::getEndTime, startTime, endTime)    // 预约结束时间在查询时间段内
                    .or()
                    .and(v -> v
                        .le(Reservation::getStartTime, startTime)            // 预约时间段包含查询时间段
                        .ge(Reservation::getEndTime, endTime)
                    )
                )
        );
        
        // 3. 将预约按座位ID分组
        Map<Long, List<Reservation>> reservationMap = reservations.stream()
            .collect(Collectors.groupingBy(Reservation::getSeatId));
        
        // 4. 转换为VO对象，判断座位是否被占用
        List<SeatAvailabilityVO> result = seats.stream().map(seat -> {
            SeatAvailabilityVO vo = new SeatAvailabilityVO();
            vo.setId(seat.getId());
            vo.setSeatNumber(seat.getSeatNumber());
            
            // 判断该座位在指定时间段是否有预约，忽略数据库中的is_occupied字段
            List<Reservation> seatReservations = reservationMap.get(seat.getId());
            vo.setIsOccupied(seatReservations != null && !seatReservations.isEmpty());
            
            return vo;
        }).collect(Collectors.toList());

        log.info("查询结果 - 总座位数: {}, 已占用座位数: {}", 
            result.size(),
            result.stream().filter(SeatAvailabilityVO::getIsOccupied).count()
        );
        
        return result;
    }

    @Transactional
    @Override
    public boolean save(StudyRoom studyRoom) {
        // 保存自习室信息
        boolean result = super.save(studyRoom);
        
        if (result) {
            // 自习室创建成功后，自动创建25个座位
            createDefaultSeats(studyRoom.getId());
        }
        
        return result;
    }
    
    /**
     * 为新自习室创建默认座位
     * @param roomId 自习室ID
     */
    private void createDefaultSeats(Long roomId) {
        // 获取自习室信息，读取座位数量
        StudyRoom studyRoom = this.getById(roomId);
        if (studyRoom == null) {
            log.error("创建座位失败：找不到ID为{}的自习室", roomId);
            return;
        }
        
        // 使用totalSeats字段获取座位总数
        Integer totalSeats = studyRoom.getTotalSeats();
        if (totalSeats == null || totalSeats <= 0) {
            log.warn("自习室座位数量无效({}), 默认创建25个座位", totalSeats);
            totalSeats = 25;
        }
        
        // 限制最大座位数为25
        int seatCount = Math.min(totalSeats, 25);
        log.info("为自习室[{}]创建{}个座位", roomId, seatCount);
        
        List<Seat> seats = new ArrayList<>();
        
        // 创建指定数量的座位，编号从1开始
        for (int i = 1; i <= seatCount; i++) {
            Seat seat = new Seat();
            seat.setRoomId(roomId);
            seat.setSeatNumber(String.valueOf(i));
            seat.setStatus(1);  // 默认状态为可用
            // 根据实际实体类设置时间
            seat.setCreatedAt(LocalDateTime.now());
            seat.setUpdatedAt(LocalDateTime.now());
            
            seats.add(seat);
        }
        
        // 批量保存座位
        if (!seats.isEmpty()) {
            log.info("批量保存{}个座位", seats.size());
            seatService.saveBatch(seats);
        }
    }

    @Transactional
    public StudyRoom createStudyRoom(StudyRoom studyRoom) {
        // 设置创建时间等信息
        studyRoom.setCreatedAt(LocalDateTime.now());
        studyRoom.setUpdatedAt(LocalDateTime.now());
        
        // 保存自习室
        boolean saved = this.save(studyRoom);
        
        if (saved) {
            // 自动创建25个座位
            createDefaultSeats(studyRoom.getId());
            return studyRoom;
        }
        
        throw new ServiceException("创建自习室失败");
    }

    @Override
    public List<StudyRoom> list() {
        LambdaQueryWrapper<StudyRoom> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StudyRoom::getIsDeleted, 0); // 只查询未删除的
        return super.list(wrapper);
    }

    @Override
    public StudyRoom getById(Serializable id) {
        LambdaQueryWrapper<StudyRoom> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StudyRoom::getId, id);
        wrapper.eq(StudyRoom::getIsDeleted, 0); // 只查询未删除的
        return super.getOne(wrapper);
    }
} 